package heap

import "gvm/classfile"

type MethodRef struct {
	MemberRef
	method *Method
}

func NewMethodRef(cp *ConstantPool, methodRef *classfile.Constant_Method_Ref) *MethodRef {
	ref := &MethodRef{}
	ref.constantPool = cp
	ref.copyMethod(methodRef)
	return ref
}

func (self *MethodRef) ResolveMethod() *Method {
	if self.method == nil {
		self.resolveMethod()
	}
	return self.method
}

func (self *MethodRef) resolveMethod() {
	cf := self.constantPool.class
	kc := self.ResolveClass()
	method := lookupMethod(kc, self.name, self.descriptor)
	if method == nil {
		panic("java.lang.NoSuchFileError")
	}
	if !method.isAccessibleTo(cf) {
		panic("java.lang.IllegalAccessError")
	}
	self.method = method
}

func (self *MethodRef) ResolvedClass() *Klass {
	return self.ResolveClass()

}

func (self *MethodRef) ResolvedMethod() *Method {
	return self.ResolveMethod()
}

func (self *MethodRef) Name() string {
	return self.name
}

func (self *MethodRef) Descriptor() string {
	return self.descriptor
}

func lookupMethod(c *Klass, name string, descriptor string) *Method {
	for _, method := range c.methods {
		if method.name == name && method.descriptor == descriptor {
			return method
		}
	}
	for _, iface := range c.interfaces {
		if method := lookupMethod(iface, name, descriptor); method != nil {
			return method
		}
	}
	if c.superClass != nil {
		return lookupMethod(c.superClass, name, descriptor)
	}
	return nil
}
